let add = a => b => c => d => {
  return a + b + c + d;
};

let r = uncurrying(add)(1, 2, 3, 4);
console.log(r);

function uncurrying(fn) {
  return (...args) => {
    args.forEach(item => { //柯里化保证参数只有一个，故这样实现没毛病
      fn = fn(item);
    });
    return fn;
  };
}

//柯里化是将一个大函数 拆成一个个小函数
//反柯里化 放大函数的使用范围( 目的是扩大函数的作用范围)
//别人的东西我可以拿过来直接用，这里的this可以手动传入

let check = Object.prototype.toString.call(1); // [object Number]
//这个方法现在只能在Object.prototype上用

function uncurrying(fn){
  return (...args)=>{
    return fn.call(...args);
  }
}

let checkType = uncurrying(Object.prototype.toString);
let r = checkType(1);


//第二种写法
//确保只有函数能反柯里化
Function.prototype.uncurring = function () {
  return (...args) => {
    //Function.prototype.call 取到call方法
    //在本例中，this指向 Object.prototype.toString
    //let callFunction = Function.prototype.call;
    //callFunction中的this变成Object.prototype.toString
    //所以下面这一句等价于 Object.prototype.toString.call(1)
    // return Function.prototype.call.apply(this, args); //等价于 this.call(...args)
    //上下等价
    return this.call(...args) //apply将所有接受的参数封到一个数组里 call接受的是
  };
};
let checkType = Object.prototype.toString.uncurring();
checkType(1)
